Class Inspector
Heute hatte ich einen merkwürdigen Fehler: Ich konnte eine inaktive Klasse nicht aktivieren. Der Class Builder hat nur gemeldet: “Active class has been generated”, aber die Klasse war weiterhin inaktiv. Bei der Fehlersuche bin ich zwar nicht auf die Ursache gestoßen, habe aber einige Funktionsbausteine und Klassen kennengelernt, die bei der Fehlersuche hilfreich waren.
Mit Hilfe des Funktionsbausteins RS_INACTIVE_PART habe ich immerhin herausgefunden, welcher Teil der Klasse nicht aktiv war, aber da die Komponenten einer Klasse sehr uneinheitlich definiert werden, half es mir nicht weiter, dass der inaktive Part vom Typ “CLSD” war. Über die Tabelle DWINACTIV habe ich den Include des inaktiven Klassenartefakts ermitteln können. Über den Objekttyp habe ich zwar herausgefunden, dass dies der Teil “CLSD – LIMU CLSD Class Definition (ABAP Objects)” ist. Da der Definitionsteil im Class Builder jedoch als aktiv angezeigt wurde, wollte ich den Quelltext vergleichen. Im Artikel über die Classname Services habe ich bereits beschrieben, wie man über die Einzelteile an die technischen Details kommt. Das war mir natürlich deutlich zu Umständlich… Also habe ich letztendlich ein kleines Programm – einen Class Inspector – geschrieben, dass die einzelnen Includes einer Klasse auflistet und über Doppelklick den jeweiligen Quelltext anzeigt.
Code github
Der Quelltext ist auf github verfügbar:
https://github.com/tricktresor/class_inspector
Da das Coding so lang aber auch nicht ist, hier auch noch mal direkt.
Code
REPORT ztrcktrsr_class_inspector.
PARAMETERS p_clas TYPE seoclsname DEFAULT 'CL_GUI_CONTAINER'.
CLASS lcl_main DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF _include,
repid TYPE syrepid,
descr TYPE c LENGTH 60,
exposure TYPE icon_d,
END OF _include,
_includes TYPE STANDARD TABLE OF _include WITH EMPTY KEY.
METHODS on_double_click
FOR EVENT double_click OF cl_salv_events_table
IMPORTING row column.
METHODS constructor
IMPORTING
container_grid TYPE REF TO cl_gui_container
container_code TYPE REF TO cl_gui_container.
METHODS display.
METHODS editor.
METHODS start
IMPORTING
i_class TYPE clike.
PROTECTED SECTION.
DATA mt_redef TYPE STANDARD TABLE OF seoredef.
DATA container_grid TYPE REF TO cl_gui_container.
DATA container_code TYPE REF TO cl_gui_container.
DATA mo_editor TYPE REF TO cl_gui_abapedit.
DATA class_includes TYPE _includes.
DATA grid TYPE REF TO cl_salv_table.
DATA classname TYPE seoclsname.
METHODS display_source IMPORTING include TYPE programm.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD constructor.
me->container_grid = container_grid.
me->container_code = container_code.
ENDMETHOD.
METHOD on_double_click.
editor( ).
DATA(source) = class_includes[ row ].
display_source( source-repid ).
ENDMETHOD.
METHOD display_source.
DATA lt_source TYPE STANDARD TABLE OF string.
READ REPORT include INTO lt_source.
mo_editor->set_text( lt_source ).
ENDMETHOD.
METHOD editor.
CHECK container_code IS BOUND.
CHECK mo_editor IS INITIAL.
mo_editor = NEW #( parent = container_code ).
mo_editor->set_readonly_mode( 1 ).
ENDMETHOD.
METHOD display.
IF grid IS INITIAL.
TRY.
" create SALV
CALL METHOD cl_salv_table=>factory
EXPORTING
r_container = container_grid
IMPORTING
r_salv_table = grid
CHANGING
t_table = class_includes.
grid->get_functions( )->set_all( ).
grid->get_display_settings( )->set_list_header( CONV #( classname ) ).
DATA(columns) = grid->get_columns( ).
CAST cl_salv_column_table( columns->get_column( 'EXPOSURE' ) )->set_icon( abap_true ).
columns->get_column( 'DESCR' )->set_medium_text( 'Description' ).
columns->get_column( 'EXPOSURE' )->set_medium_text( 'Exposure' ).
" register event DOUBLE_CLICK
SET HANDLER on_double_click FOR grid->get_event( ).
grid->display( ).
CATCH cx_salv_error INTO DATA(error).
MESSAGE error TYPE 'I'.
ENDTRY.
ELSE.
grid->refresh( ).
ENDIF.
ENDMETHOD.
METHOD start.
DATA textpool TYPE table_of_textpool.
DATA description TYPE string.
CHECK classname <> i_class.
classname = i_class.
TRY.
DATA(classinfo) = cl_oo_class=>get_instance( i_class ).
CATCH cx_class_not_existent ##no_handler.
ENDTRY.
DATA(includes) = cl_oo_classname_service=>get_all_class_includes( class_name = i_class ).
CLEAR class_includes.
LOOP AT includes INTO DATA(include).
READ TEXTPOOL include INTO textpool LANGUAGE sy-langu.
IF include+30(1) = 'C'.
IF include+30(2) = 'CM'.
cl_oo_classname_service=>get_method_by_include(
EXPORTING
incname = include
RECEIVING
mtdkey = DATA(method)
EXCEPTIONS
class_not_existing = 1
method_not_existing = 2
OTHERS = 3 ).
IF sy-subrc = 0.
description = method-cpdname.
TRY.
DATA(methodexposure) = classinfo->get_component_exposure( cpdname = method-cpdname ).
CATCH cx_component_not_existing ##no_handler.
ENDTRY.
ENDIF.
ELSE.
CASE include+30(5).
WHEN 'CCDEF'.
description = 'Local type definitions'.
WHEN 'CCMAC'.
description = 'Macros'.
WHEN 'CCIMP'.
description = 'Local class implementations'.
WHEN 'CCAU'.
description = 'Unit tests'.
WHEN 'CU'.
description = 'Class definition/ Public section'.
WHEN 'CO'.
description = 'Protected section'.
WHEN 'CI'.
description = 'Private Section'.
WHEN 'CP'.
description = 'Class pool'.
WHEN 'CT'.
description = ''.
WHEN 'CL'.
description = 'Local classes'.
WHEN 'CS'.
description = 'Complete source code'.
ENDCASE.
ENDIF.
ENDIF.
APPEND VALUE #(
repid = include
descr = description
exposure = SWITCH #( methodexposure
WHEN seoc_exposure_private THEN icon_led_red
WHEN seoc_exposure_protected THEN icon_led_yellow
WHEN seoc_exposure_public THEN icon_led_green )
) TO class_includes.
ENDLOOP.
display( ).
ENDMETHOD.
ENDCLASS.
INITIALIZATION.
DATA(docker) = NEW cl_gui_docking_container( side = cl_gui_docking_container=>dock_at_bottom ratio = 95 ).
DATA(splitter) = NEW cl_gui_easy_splitter_container(
parent = docker
orientation = cl_gui_easy_splitter_container=>orientation_horizontal ).
DATA(container_grid) = splitter->top_left_container.
DATA(container_code) = splitter->bottom_right_container.
DATA(main) = NEW lcl_main(
container_grid = container_grid
container_code = container_code ).
AT SELECTION-SCREEN.
main->start( p_clas ).
START-OF-SELECTION.
- Interview mit Björn Schulz (Software-Heroes.com) - 3. September 2024
- Daten aus ALV ermitteln - 3. September 2024
- So lange es den SAPGUI noch gibt… - 27. Juni 2024